package com.pi.pro.xcmg.am.was.fac.calculator;

import com.pi.common.CodesConstants;
import com.pi.framework.core.util.StringUtils;
import com.pi.pro.xcmg.am.common.XcmgAmConstants;
import com.pi.wms.dto.act.AllocationActionDto;
import com.pi.wms.dto.act.AllocationLineDto;
import com.pi.wms.entity.*;
import com.pi.wms.fac.TaskBuilder;
import com.pi.wms.fac.impl.BaseShipAllocator;
import com.pi.wms.service.CustDyncdataQueryService;
import com.pi.wms.service.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *  分配计算/波次,批次属性[精确+通配]
 */
@Slf4j
public class WaveLotattrShipAllocator extends BaseShipAllocator {


    @Autowired
    private TaskService taskService;

    @Autowired
    private CustDyncdataQueryService soCustDyncdataQueryService;

    @Autowired
    private TaskBuilder taskBuilder;

    public WaveLotattrShipAllocator(){
        this.code = CodesConstants.COMMON_WILDCARD + "/"  + XcmgAmConstants.SHIP_RULE_WAVE_LOTATTR_ALLOCATOR;
    }

    public WaveLotattrShipAllocator(String code){
        super(code);
    }

    public List<TwtActAllocationList> allocate(String batchNumber, AllocationLineDto dataDto, AllocationActionDto actionDto) {
        log.debug("Facility WaveLotattrShipAllocator start://{allocation:{}, action:{}}", dataDto,actionDto);
        List<TwtActAllocationList> allocations=null;
        if ((dataDto==null) || (dataDto.getRefMaterialId()==null) || (dataDto.getQuantity()==null)){
            return allocations;
        }
        TwaDocWaveHeader header=null;
        TwaDocWaveDetails line=null;
        String lotnum="";
        Long materialid=dataDto.getRefMaterialId();

        if (dataDto.getRefDocumentDetailsId()!=null){
            line=this.waveDetailsService.findById(dataDto.getRefDocumentDetailsId());
            if (line==null){
                actionDto.errorResult("cant found doc line.id="+String.valueOf(dataDto.getRefDocumentDetailsId()));
                return allocations;
            }
            header=this.waveService.findById(line.getHeaderId());
            if (header==null){
                actionDto.errorResult("cant found doc.id="+String.valueOf(line.getHeaderId()));
                return allocations;
            }
        }else {
            if (StringUtils.isNullOrBlank(dataDto.getDocumentNumber())){
                actionDto.errorResult("document number is blank");
                return allocations;
            }
            if (StringUtils.isNullOrBlank(dataDto.getDocumetLineNumber())){
                actionDto.errorResult("document line number is blank");
                return allocations;
            }
            header=this.waveService.findByDocumentNumber(dataDto.getDocumentNumber().trim());
            if (header==null){
                actionDto.errorResult("cant found doc.number="+dataDto.getDocumentNumber());
                return allocations;
            }
            line=this.waveDetailsService.findByDocumentLine(dataDto.getDocumentNumber().trim(), dataDto.getDocumetLineNumber().trim());
            if (line==null){
                actionDto.errorResult("cant found doc line.id="+String.valueOf(dataDto.getRefDocumentDetailsId()));
                return allocations;
            }
        }
        if (line!=null){
            if (!materialid.equals(line.getMaterialId())){
                actionDto.errorResult("material not match.document="+dataDto.getDocumentNumber());
                return allocations;
            }
            lotnum="";
            if (!StringUtils.isNullOrBlank(line.getLotattr05())){
                lotnum=line.getLotattr05().trim();
            }
            if (!StringUtils.isNullOrBlank(line.getCheckLotNumber())){
                lotnum=line.getCheckLotNumber().trim();
            }
        }



        //
        Map<String, TwtActTaskList> containers=new HashedMap();
        /**
        List<TwtActTaskList> tasks=this.taskService.queryWorkingTasks(WmsConstants.TASK_TYPE_PICK);
        if ((tasks!=null)&& (tasks.size()>0)){
            for  (TwtActTaskList t:tasks){
                if (t==null){
                    continue;
                }
                if (!WmsConstants.TASK_STATUS_CREATE.equalsIgnoreCase(t.getStatus())){
                    containers.put(t.getFromContainNumber(), t);
                }
            }
        }
        **/

        TwmBasLocation toLocation=this.plantoLocation(null, dataDto,header,line,null,null,actionDto);
        List<VwaInventoryStorageList> storageDatas=this.soCustDyncdataQueryService.matchInventory(header.getDivisionId(), header, line);
        VwaInventoryStorageList storageData=null;
        TwaInventoryDetails storage=null;
        if ((storageDatas==null) || (storageDatas.size()==0)){
            actionDto.errorResult("can't found inventory.document="+dataDto.getDocumentNumber());
            return allocations;
        }
        TwmBasLocation dock=null;
        BigDecimal total=dataDto.getQuantity();
        BigDecimal qtyopen=null;
        int index=0;
        storageData=storageDatas.get(index);
        allocations=new ArrayList<>();
        TwtActAllocationList allocation=null;
        List<TwaInventoryDetails> changedstorages=new ArrayList<>();
        Map<Long,Long> allocationMapping=this.storageResolver.allocationList();
        while ((total.compareTo(BigDecimal.ZERO)>0) && (storageData!=null)) {
            if (storageData == null) {
                index++;
                if (index >= storageDatas.size()) {
                    break;
                }
                storageData = storageDatas.get(index);
                continue;
            }
            if (index > storageDatas.size()) {
                break;
            }
            //
            if (allocationMapping.get(storageData.getId()) != null) {
                index++;
                if (index >= storageDatas.size()) {
                    break;
                }
                storageData = storageDatas.get(index);
                continue;
            }
            storage = this.inventoryService.findById(storageData.getId());
            if ((storage.getQty() == null) || (storage.getQty().compareTo(BigDecimal.ZERO) <= 0)) {
                index++;
                if (index >= storageDatas.size()) {
                    break;
                }
                storageData = storageDatas.get(index);
                continue;
            }
            if ((containers != null) && (containers.containsKey(storage.getContainNumber()))) {
                log.error("Facility LotnumPickSequenceShipBatchAllocator allocate skip//{header:{}, line:{}, container:{}, storageid:{}}", header.getDocumentNumber(), line.getMaterialCode(), storage.getContainNumber(), storage.getId());
                continue;
            }
            if ((storage.getQtyAllocated() != null) && (storage.getQtyAllocated().compareTo(storage.getQty()) >= 0)) {
                index++;
                if (index >= storageDatas.size()) {
                    break;
                }
                storageData = storageDatas.get(index);
                continue;
            }
            qtyopen = storage.getQty();
            if (storage.getQtyAllocated() != null) {
                qtyopen = qtyopen.subtract(storage.getQtyAllocated());
            }
            if (!bulkAllocate(actionDto)) {
                if (qtyopen.compareTo(total) > 0) {
                    qtyopen = total;
                }
            }
            //TODO:HU/202311
            //每笔重新分配
            //if (toLocation==null){
            toLocation = this.plantoLocation(batchNumber, dataDto, header, line, storage, qtyopen, actionDto);
            //}
            dock = this.plantoDock(header);
            if (dock!=null){
                toLocation=dock;
            }
            //}
            allocation = allocationService.create(batchNumber, header, line, storage, qtyopen, toLocation, this.taskBuilder, actionDto);
            if (allocation==null){
                return allocations;
            }
            if (!StringUtils.isNullOrBlank(line.getDEdi13())){
                allocation.setUdf09(line.getDEdi13().trim());
                this.allocationService.save(allocation);
            }

            allocations.add(allocation);
            changedstorages.add(storage);
            if (this.inventoryService.holding(storage)){
                this.storageResolver.cacheAllocate(storage.getId(),allocation.getId());
            }

            //
            total=total.subtract(qtyopen);
            if (total.compareTo(BigDecimal.ZERO)<=0){
                break;
            }
            index++;
            if (index>=storageDatas.size()){
                break;
            }
            storageData=storageDatas.get(index);
        }
        //
        try{
            if ((changedstorages!=null)&&(changedstorages.size()>0)){
                for (TwaInventoryDetails cd:changedstorages){
                    if (cd==null){
                        continue;
                    }
                    cd=this.inventoryService.reload(cd);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return allocations;
    }

    private boolean bulkAllocate(AllocationActionDto actionDto){
        if (actionDto==null){
            return false;
        }
        if (actionDto.getBulkMode()==null){
            return false;
        }
        if (!CodesConstants.COMMON_FLAG_YES.equalsIgnoreCase(actionDto.getBulkMode())){
            return false;
        }
        return true;
    }

}
